package cn.itcast.nems.payment.web.controller.o;

import cn.itcast.nems.common.account.AccountHolder;
import cn.itcast.nems.common.account.AccountInfo;
import cn.itcast.nems.common.tenant.TenantInfo;
import cn.itcast.nems.common.tenant.TenantInfoHolder;
import cn.itcast.nems.manager.payment.PaymentProperties;
import cn.itcast.nems.payment.dto.PaymentCallbackDTO;
import cn.itcast.nems.payment.dto.StudentPaidDTO;
import cn.itcast.nems.payment.service.PaymentService;
import cn.itcast.nems.payment.util.RSA2ForMchtUtils;
import com.alibaba.fastjson.JSON;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.Map;

@RestController("opaymentController")
@RequestMapping("/o/payment")
@Slf4j
@RequiredArgsConstructor
public class PaymentController {

    private final PaymentService paymentService;

    private final PaymentProperties paymentProperties;

    /**
     * 支付同步回调接口
     */
    @GetMapping("/sync/callback")
    public ResponseEntity<String> syncCallback() {
        log.info("[支付同步回调]进入");
        return ResponseEntity.ok("<div style='font-weight:600; font-size:50px'>支付完成!</div>");
    }

    /**
     * 支付异步回调接口
     */
    @PostMapping("/async/callback")
    public ResponseEntity<Map<String, String>> asyncCallback(@RequestBody Map<String, String> requestBody) {
        String requestBodyStr = JSON.toJSONString(requestBody);
        log.info("[支付异步回调]进入, 报文:{}", requestBodyStr);
        PaymentCallbackDTO paymentCallbackDTO = JSON.parseObject(requestBodyStr, PaymentCallbackDTO.class);
        String bizParams = paymentCallbackDTO.getBizParams();
        // 回调的业务参数
        PaymentCallbackDTO.BizParams bizParamCallbackDTO = JSON.parseObject(bizParams, PaymentCallbackDTO.BizParams.class);
        String merchantOrderNo = bizParamCallbackDTO.getMerchantOrderNo();
        boolean signStatus = RSA2ForMchtUtils.rsa2Check(requestBody, paymentProperties.getItcastPay().getPublicKey());
        if (!signStatus) {
            log.info("[支付异步回调]验证签名失败, sign:{}, merchantOrderNo:{}", paymentCallbackDTO.getSign(), merchantOrderNo);
            return ResponseEntity.ok(buildFailResponse(merchantOrderNo, "签名验证失败"));
        }
        log.info("[支付异步回调]验证签名成功, sign:{}, merchantOrderNo:{}", paymentCallbackDTO.getSign(), merchantOrderNo);
        paymentCallbackDTO.setBizDto(bizParamCallbackDTO);
        // 子订单信息
        PaymentCallbackDTO.SubOrder subOrderDto = JSON.parseObject(bizParamCallbackDTO.getSubOrder(), PaymentCallbackDTO.SubOrder.class);
        bizParamCallbackDTO.setSubOrderDto(subOrderDto);
        try {
            AccountHolder.setAccountInfo(new AccountInfo("", "", "", ""));
            TenantInfoHolder.setTenantInfo(TenantInfo.DEFAULT_TENANT_INFO);
            this.paymentService.callback(paymentCallbackDTO);
        } catch (Exception e) {
            log.error("[支付异步回调]支付失败", e);
            return ResponseEntity.ok(buildFailResponse(merchantOrderNo, "支付失败"));
        } finally {
            AccountHolder.clear();
            TenantInfoHolder.clear();
        }
        return ResponseEntity.ok(buildSuccessResponse(merchantOrderNo, "支付成功"));
    }

    /**
     * 学员支付回调接口
     */
    @PostMapping("/student/paid")
    public ResponseEntity<String> studentPaid(@RequestBody @Validated StudentPaidDTO studentPaidDTO) {
        try {
            log.info("学员有支付: {}", studentPaidDTO);
            TenantInfoHolder.setDefaultTenantInfo();
            AccountHolder.setAccountInfo(new AccountInfo("", "", "", ""));
            this.paymentService.studentPaid(studentPaidDTO);
            return ResponseEntity.ok("success");
        }finally {
            TenantInfoHolder.clear();
            AccountHolder.clear();
        }
    }

    /**
     * 构建一个失败的返回结果
     *
     * @param merchantOrderNo 订单号
     * @param msg             失败详情
     * @return 返回结果
     */
    private static Map<String, String> buildFailResponse(String merchantOrderNo, String msg) {
        Map<String, String> resultMap = new HashMap<>(3);
        resultMap.put("return_code", "FAIL");
        resultMap.put("return_msg", msg);
        resultMap.put("merchant_order_no", merchantOrderNo);
        return resultMap;
    }

    /**
     * 构建一个成功的返回结果
     *
     * @param merchantOrderNo 订单号
     * @param msg             成功信息
     * @return 返回结果
     */
    private static Map<String, String> buildSuccessResponse(String merchantOrderNo, String msg) {
        Map<String, String> resultMap = new HashMap<>(3);
        resultMap.put("return_code", "SUCCESS");
        resultMap.put("return_msg", msg);
        resultMap.put("merchant_order_no", merchantOrderNo);
        return resultMap;
    }


}
